// @ts-nocheck
// eslint-disable-next-line no-extra-boolean-cast
import * as ElementPlus from "element-plus"

// import { ElCol, ElForm, ElFormItem, ElInput, ElRow, ElRadio, ElRadioGroup } from "element-plus"
// import { ElButton } from "element-plus/dist/index.full.mjs"
import {
  h,
  render,
  getCurrentInstance,
  markRaw,
  defineComponent,
  resolveComponent,
  Fragment,
  nextTick,
  inject,
  watch
} from "vue"
import { NextTick } from "../utils/common"

const ruleConf = {
  required: (item) => {
    if (item.strict) {
      return {
        validator: (rule, value, callback) => {
          if (!value || value === "")
            callback(new Error(`${item.ruleLabel}不能为空`))
          else callback()
        },
        trigger: item.trigger || "change"
      }
    }
    return {
      required: true,
      message: `${item.ruleLabel}不能为空`,
      trigger: item.trigger || "change"
    }
  },
  number: (item) => {
    return {
      validator: (rule, value, callback) => {
        if (!item.strict) {
          value = Number(value)
        }
        if (!(typeof value === "number" && Number.isFinite(value)))
          callback(new Error(`${item.ruleLabel}必须为数字`))
        if (value < (item.min ?? item.minNumber)) {
          callback(
            new Error(`${item.ruleLabel}不能小于${item.min ?? item.minNumber}`)
          )
        }
        if (value > (item.max ?? item.maxNumber)) {
          callback(
            new Error(`${item.ruleLabel}不能大于${item.max ?? item.maxNumber}`)
          )
        } else callback()
      },
      trigger: "change"
    }
  },
  custom: (item) => {
    return {
      validator: item.validator,
      message: item.message,
      trigger: item.trigger || "blur"
    }
  },
  minNumber: (item) => {
    return {
      validator: (rule, value, callback) => {
        if (!(typeof value === "number" && Number.isFinite(value)))
          callback(new Error(`${item.ruleLabel}必须为数字`))
        if (value < item.minNumber) {
          callback(new Error(`${item.ruleLabel}不能小于${item.minNumber}`))
        } else callback()
      },
      trigger: "change"
    }
  }
}
const debounce = function (fun, delay = 300) {
  let timer
  return function () {
    let ctx = this
    let args = arguments
    let arr = Array.from(arguments)
    if (timer) {
      clearTimeout(timer)
    }
    if (arr.indexOf("immediate") > -1) {
      fun.apply(ctx, args)
      return
    }
    timer = setTimeout(() => {
      timer = null
      try {
        fun.apply(ctx, args)
      } catch (error) {
        console.log(error) //?
      }
    }, delay)
  }
}
const deepClone = (obj) => {
  if (obj === null) return null // 如果是 null 直接返回 null
  if (typeof obj !== "object") return obj // 如果 obj 没有子属性直接返回 obj

  let clone = Array.isArray(obj) ? [] : {}
  for (let key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      clone[key] = deepClone(obj[key]) // 递归调用 deepClone 进行深度拷贝
    }
  }
  return clone
}
const getTargetDom = (e, flg, loop = 0) => {
  if (flg(e)) {
    return e
  } else {
    loop += 1
    if (loop > 8) return null
    if (!e?.parentNode) {
      return null
    }
    return getTargetDom(e.parentNode, flg, loop)
  }
}
export default defineComponent({
  props: [
    "formConf",
    // "_parent",
    "clickEvent",
    "visible",
    "dragEvent",
    "evalFunction",
    "changeFunc",
    "useIf",
    "isBind" //!v-model
    // "slotName"
  ],
  data() {
    let formName = "formCom_" + Math.ceil(Math.random() * 10 ** 6)
    //if (ctx?.formConf?.name) formName = ctx.formConf.name;

    return {
      isCom: false, //根据formConf.template是否为数组判断是否直接渲染组件
      // formData: null,
      form: { name: "test" },
      formName,
      customCom: {},
      show: false,
      mergeProp: ["class", "style"],
      unDragList: ["ElOption", "ElRadio"],
      currentCom: null,
      formProp_conf: {},
      rules: {},
      lastRuleConf: "unset"
    }
  },
  // watch: {
  //   formConf: {
  //     immediate: true,
  //     handler(nv) {
  //       if (!nv.template) return
  //       this.isCom = !Array.isArray(nv.template)
  //     }
  //   }
  // },
  created() {
    let ctx = this

    // ctx.getForm = inject('formData')
    // ctx.form = ctx.getForm.formConf.props.model ?? {}
    ctx.form = ctx.formConf?.props?.model //markRaw(ctx.formConf?.props?.model ?? {});
    //  if (ctx.formConf?.props?.model) ctx.formData = ctx.formConf.props.model;
    ctx.evalFunc = ctx.evalFunction ?? inject("evalFunc")
    if (!ctx.evalFunc)
      ctx.evalFunc = (str) => {
        console.log("未创建evalFunc!", str)
      }
    ctx.init(ctx)
  },
  methods: {
    getRules(rules = {}) {
      let ctx = this
      let newRules = deepClone(rules)
      Object.assign(newRules, ctx.formProp_conf)
      let ruleObj = {}
      Object.keys(newRules).forEach((k) => {
        let field = k
        let fieldRulesArr = []
        Object.keys(newRules[k]).forEach((rk) => {
          if (typeof ruleConf[rk] == "function") {
            let item = newRules[k][rk]
            if (!item) return
            ///执行eval 动态绑定
            Object.keys(item).forEach((kk) => {
              if (kk.startsWith("_")) {
                ////bind变量
                let name = /(?<=_).*/.exec(kk)[0]
                let val
                if (typeof item[k] == "function") val = item[kk]
                else
                  val =
                    ctx.getValInParent(item[kk]) ??
                    ctx.form[item[kk]] ??
                    undefined
                if (val === undefined) return
                item[name] = val
              }
            })
            let conf = ctx.formProp_conf[k] ?? {}
            if (!item?.ruleLabel) {
              item.ruleLabel =
                newRules[k].ruleLabel ??
                (conf._label && ctx.getValInParent(conf._label)) ??
                conf.label ??
                conf.contentText ??
                ""
            }

            fieldRulesArr.push(ruleConf[rk](newRules[k][rk]))
          }
        })
        ruleObj[field] = fieldRulesArr
      })
      return ruleObj
    },
    updateRule: debounce(function (refresh = false) {
      let ctx = this

      if (!refresh) {
        try {
          if (
            JSON.stringify(ctx.lastRuleConf) ==
            JSON.stringify(ctx.formProp_conf)
          ) {
            return
          }
        } catch (error) {}
      }
      ctx.lastRuleConf = markRaw(deepClone(ctx.formProp_conf))
      ctx.rules = ctx.getRules(ctx.formConf?.rulesConf)

      ctx.$nextTick(async () => {
        if (ctx.$refs[ctx.formName]) {
          // ctx.$refs[ctx.formName].resetFields();
          ctx.$refs[ctx.formName].clearValidate()
          ctx.$refs[ctx.formName].validate()
          //? change
        }
      })

      // ;(async () => {
      //   await nextTick()
      //   if (childRule.value.length) {
      //     for (let e of childForm.value) {
      //       await e.validate((valid) => {
      //         return valid
      //       })
      //     }
      //   }
      // })()
    }),
    // changeFormData(prop: any, val: any) {
    //   console.log("changeFormData", prop, val)
    //   this.formConf.props.model[prop] = val
    //   //this.$emit('changeFormData', {prop, val})
    // },
    strToLower(str) {
      return str
        .replace(/([A-Z])/g, "-$1")
        .toLowerCase()
        .substring(1)
    },
    toCamelCase(str) {
      // 将字符串按照 - 或 _ 进行分割
      const words = str.split(/[-_]/)
      // 将第一个单词保持不变，其余单词首字母大写后拼接
      const result = words.reduce((acc, curr, index) => {
        if (index === 0 && curr !== "el") {
          // 不对第一个单词进行修改
          return curr + acc
        }
        //return str
        // 将首字母大写后拼接
        return acc + curr.charAt(0).toUpperCase() + curr.slice(1)
      }, "")
      return result
    },
    getValInParent(str, varys: Object = {}, ...args) {
      let ctx = this
      let res = null
      // let v2 = !!ctx.$parent?.form || !!ctx?._parent?.form
      // if (!v2 && typeof ctx.evalFunc === "function") {
      res = ctx.evalFunc(str, varys, args)
      return res
      // }

      // res = function () {
      //   return eval(str)
      // }.bind(ctx.$parent)()
      // return res
    },
    // getValInParent(str, varys: Object = {}, ...args) {
    //   let ctx = this;
    //   if (!that) that = ctx.evalFunc("this");
    //   let paras = {
    //     // this: that,
    //     varys,
    //     form: ctx.form,
    //   }; ///form 为特殊字符
    //   let paraArr = [];
    //   let valArr = [];
    //   Object.keys(paras).forEach((k) => {
    //     let regexStr = "\\b" + k + "\\b";
    //     let regex = new RegExp(regexStr);
    //     if (regex.test(str)) {
    //       paraArr.push(k);
    //       valArr.push(paras[k]);
    //     }
    //   });
    //   try {
    //     let func = new Function(...paraArr, "return " + str);
    //     let res = func.call(that, ...valArr); /////////? 更改form值 触发render????
    //     return res;
    //   } catch (error) {
    //     if (str.startsWith("(") || str.startsWith("function(")) {
    //       return new Function(str);
    //     }
    //   }

    //   // let res = null;
    //   // let v2 = !!ctx.$parent?.form || !!ctx?._parent?.form
    //   // if (!v2 && typeof ctx.evalFunc === "function") {
    //   // res = ctx.evalFunc(str, varys, args);
    //   // return res;
    //   // }

    //   // res = function () {
    //   //   return eval(str)
    //   // }.bind(ctx.$parent)()
    //   // return res
    // },
    init(_ctx) {
      let customCom = window._customComponents ?? {}
      if (!window._customComponents) {
        for (const [key, com] of Object.entries(ElementPlus)) {
          customCom[key] = com
        }
      }

      this.customCom = markRaw(customCom)
      // if (ctx.formConf.rules) {
      // }
    },
    bindEvents(conf: any) {
      let ctx = this

      // let attr = conf.formItemProps?.formProp || conf.formProp || conf.formItemProps?.prop || conf.prop
      // if (!attr || !ctx.formConf.props?.model || !ctx.formConf.props?.model[attr]) return conf //常量

      if (Array.isArray(conf)) {
        return conf.map((e) => e && ctx.bindEvents(e))
      }
      let getParaRegex = /\((.*?)\)/

      Object.keys(conf).forEach((k) => {
        let oriFunc = conf[k]
        //增加事件方法变量
        if (k.startsWith("_on") && oriFunc) {
          oriFunc = ctx.getValInParent(oriFunc, conf.varys)
          // if (ctx.clickEvent) {
          //   conf[k] = (e) => {
          //     let str = typeof oriFunc == 'function' ? oriFunc.toString() : oriFunc
          //     if (k.includes('lick')) {
          //       ctx.$emit(ctx.clickEvent, conf, e)
          //     }
          //     e.stopPropagation();
          //   }
          //   return
          // }
          if (!conf?.varys || JSON.stringify(conf.varys) === "{}") return
          if (typeof oriFunc == "function" && oriFunc.length) {
            let funcStr = oriFunc?.toString() ?? ""
            let params = getParaRegex.exec(funcStr)[1]?.split(",") ?? []
            let paraArr = new Array(params.length).fill(undefined)
            conf[k] = function (...args: any) {
              let argIndex = 0
              params.forEach((e, i) => {
                e = e.trim()
                if (e === "varys" || e === "varys2") {
                  //////?
                  paraArr[i] = conf.varys
                  return
                }

                Object.keys(conf.varys).forEach((k) => {
                  if (k === e) {
                    paraArr[i] = conf.varys[k]
                  }
                })
                if (paraArr[i] !== undefined) return

                paraArr[i] = args[argIndex]
                argIndex += 1
              })
              oriFunc(...paraArr)
            }.bind(ctx)
          }
        }
        if (k.startsWith("on") && oriFunc) {
          if (typeof oriFunc === "string") {
            let strs = getParaRegex.exec(oriFunc)[1] ?? ""
            let params = strs === "" ? strs?.split(",") : []
            let varyPara =
              params.filter((e) => {
                if (e.replaceAll(" ") === "") return false
                let flg = /["'`]/.test(e)
                return !flg
              }) ?? []
            let varystr = strs
            varyPara.forEach((e, i) => {
              varystr = varystr.replaceAll(e, `{` + i + `}`)
            })
            oriFunc = oriFunc.replace(strs, varystr)
            oriFunc = eval(
              "(" +
                varyPara.join(",") +
                ")" +
                "=> {ctx.getValInParent(`" +
                oriFunc +
                "`, conf?.varys," +
                varyPara +
                ")}"
            )
            // if (k.includes('lick')) {

            //   oriFunc(2)
            // }
          }
          if (!conf?.varys || JSON.stringify(conf.varys) === "{}") return
          if (typeof oriFunc == "function" && oriFunc.length) {
            let funcStr = oriFunc?.toString() ?? ""
            let params = getParaRegex.exec(funcStr)[1]?.split(",") ?? []
            let paraArr = new Array(params.length).fill(undefined)
            conf[k] = function (...args: any) {
              let argIndex = 0
              params.forEach((e, i) => {
                e = e.trim()
                if (e === "varys" || e === "varys2") {
                  //////?
                  paraArr[i] = conf.varys
                  return
                }

                Object.keys(conf.varys).forEach((k) => {
                  if (k === e) {
                    paraArr[i] = conf.varys[k]
                  }
                })
                if (paraArr[i] !== undefined) return

                paraArr[i] = args[argIndex]
                argIndex += 1
              })
              oriFunc(...paraArr)
            }.bind(ctx)
          }
          // let v2 = !!ctx.$parent?.form || !!ctx?._parent?.form
        }
      })

      return conf
    },
    getStr(obj: Object) {
      let newObj = {}
      Object.keys(obj).forEach((k) => {
        if (Object.prototype.toString.call(obj[k]) === "[object Object]") {
          newObj[k] = JSON.stringify(obj[k])
        } else newObj[k] = obj[k]
      })
      return newObj
    },
    getFlatJson(obj: Object, evalKeys = true, newObj = {}) {
      let ctx = this

      Object.keys(obj).forEach((k) => {
        //?change 新增varys变量处理
        if (
          k === "varys" &&
          Object.prototype.toString.call(obj[k]) === "[object Object]"
        ) {
          let newVarys = {}
          Object.keys(obj[k]).forEach((prop) => {
            if (k === "model" && ctx.isCom) {
              //渲染组件时不将绑定属性放在dom上
              return
            }
            if (prop.startsWith("_")) {
              let name = /(?<=_).*/.exec(prop)[0]
              let val =
                ctx.getValInParent(obj[k][prop], obj?.varys) ?? undefined ///////////////////////在父实例中执行

              if (val === undefined) return //
              newVarys[name] = val
            } else {
              newVarys[prop] = obj[k][prop]
            }
          })
          obj[k] = newVarys
        }
        if (k === "formItemProps") {
          if ("_prop" in obj[k]) {
            let val =
              ctx.getValInParent(obj[k]["_prop"], obj?.varys) ?? undefined
            val && (ctx.formProp_conf[val] = obj[k])
          }
          if (obj?.[k]?.prop) {
            ctx.formProp_conf[obj[k].prop] = obj[k]
          }
        }
        if (
          Object.prototype.toString.call(obj[k]) === "[object Object]" &&
          k !== "varys"
        ) {
          ctx.getFlatJson(obj[k], undefined, newObj)
        } else {
          if (evalKeys && k.startsWith("_")) {
            ////bind变量
            let name = /(?<=_).*/.exec(k)[0]
            let val = ctx.getValInParent(obj[k], obj?.varys) ?? undefined ///////////////////////在父实例中执行

            if (val === undefined) return /////????
            let prop = ctx.mergeProp.find((e) => {
              if (e === name) {
                return true
              }
            })
            if (prop && newObj[prop] !== undefined) {
              newObj[prop] += " " + val
              /////string格式 后面改
            } else newObj[name] = val ?? newObj[name]
          } else {
            newObj[k] = obj[k] ?? newObj[k]
          }
        }
      })

      return newObj
    },
    getRowItem(e: Object, no, isCustom = false) {
      let ctx = this

      let child
      if (e.defautOptions) {
        //class对象???
        e = e.value
      }
      //  if (e.components.length === 1 && e.components[0].customType) {
      ////自定义块/行元素
      //    child = ctx.getComs(e.components, undefined, isCustom)
      //  } else {
      e.varys &&
        e.components.forEach((ee) => {
          ee.varys = e.varys
        })
      child = ctx.getCols(e.components, isCustom)
      // }
      let item
      item = (
        <ElRow
          class={e.class}
          style={e.style}
          {...ctx.getFlatJson(e)} //e?.props ??
        >
          {child}
        </ElRow>
      )
      return item
    },
    getRow(conf: Array<[Object]> | Object) {
      let ctx = this

      let rowList: Array<[Object]> = []
      conf.forEach((e: any) => {
        if (!e) return
        let item = ctx.getRowItem(e)
        rowList.push(item)
      })
      return rowList
    },
    getCols(conf: Array<[Object]>, isCustom = false) {
      let ctx = this
      if (!conf) return []
      let comList: Array<[Object]> = []
      conf.forEach((e: any) => {
        if (e.defautOptions) {
          //class对象
          e = e.value
        }
        let item

        let res = deepClone(e)
        let orderList = ["v_if"] //, "v_show"
        orderList.forEach((order) => {
          if ("_" + order in e) {
            let val =
              ctx.getValInParent(res["_" + order], res?.varys) ??
              ctx.form[res["_" + order]] ??
              undefined
            res[order] = val
            delete res["_" + order]
          }
        }) //change
        if (res["v_if"] !== undefined && ctx.useIf !== false) {
          if (!res["v_if"]) return null
        }
        // if (res["v_show"] !== undefined) {
        //   res["style"] = res["style"]
        //     ? " display:none; !important"
        //     : (res["style"] += " display:none; !important");
        // }
        item = (
          <ElCol span={e.span} push={e.push} offset={e.offset}>
            {[ctx.getComs(e, undefined, isCustom)]}
          </ElCol>
        )
        comList.push(item)
      })
      return comList
    },
    getComs(conf: any, isflat = false, isCustom = false) {
      let ctx = this

      let flatConf = isflat ? conf : ctx.getFlatJson(conf, false) ////可能含v-for 先不eval
      flatConf = isflat ? flatConf : ctx.handleVueOrder(flatConf)
      if (!flatConf) return //v_if
      flatConf = isflat ? flatConf : ctx.bindEvents(flatConf)
      // if (isCustom && !flatConf.belongParent) {
      //   //块级子元素添加父组件标识
      //   ////配置未更新
      //   flatConf.belongParent = isCustom
      // }
      if (flatConf?.customType) {
        isCustom = flatConf?.customType ? flatConf.selfIndex : null
      }
      Object.keys(flatConf)?.forEach((k) => {
        ///执行eval 动态绑定
        if (k.startsWith("_")) {
          ////bind变量
          let name = /(?<=_).*/.exec(k)[0]
          let val
          if (typeof flatConf[k] == "function") val = flatConf[k]
          else
            val =
              ctx.getValInParent(flatConf[k], flatConf?.varys) ??
              ctx.form[flatConf[k]] ??
              undefined
          if (val === undefined) return
          let prop = ctx.mergeProp.find((e) => {
            if (e === name) {
              return true
            }
          })
          if (prop && flatConf[prop] !== undefined) {
            flatConf[prop] += " " + val
            /////string格式 后面改
          } else flatConf[name] = val ?? flatConf[name]
        }
      })
      if (!flatConf) return
      if (Array.isArray(flatConf)) {
        return flatConf.map((e) => {
          /////varys???
          return ctx.getComs(e, true)
        })
      }
      let renderCom
      // let com = (conf.comName?.toLowerCase().startsWith("el")
      //   ? markRaw(this.customCom[conf.comName])
      //   : conf.comName)
      let comName = ctx.toCamelCase(flatConf.comName.trim())

      const com = this.customCom[comName] ?? comName
      if (flatConf["v_model"] !== undefined) {
        if (Array.isArray(flatConf["v_model"])) {
          //[prop1][prop11]
          flatConf["v_model"].forEach((e, i) => {
            if (
              typeof e == "string" &&
              e.includes("varys.") &&
              flatConf.varys
            ) {
              //替换变量
              flatConf["v_model"][i] = eval(
                e.replaceAll("varys.", "flatConf.varys.")
              )
            }
          })
        } else {
          let str = null
          if (flatConf["v_model"]?.startsWith("form.")) {
            str = /\.([^.]*)/.exec(flatConf["v_model"])[1]
          }
          if (flatConf["v_model"]?.startsWith("form[")) {
            str = /\[(.*?)\]/.exec(flatConf["v_model"])[1]
          }
          flatConf["v_model"] = str ?? flatConf["v_model"]
          //加工格式form.x ||form['x']
        }
      }
      let bindProp = (ctx.isBind === false ? null : flatConf["v_model"])
        ? Array.isArray(flatConf["v_model"])
          ? flatConf["v_model"]
          : ctx.form[flatConf["v_model"]] ?? undefined
        : null

      const getChild = (arr, method, isCustom = false, varys) => {
        let childObj = {}
        let res = []
        let hasSlot = false
        arr.forEach((e: any) => {
          if (e.slotName) {
            hasSlot = true
          }
          varys && (e.varys = varys)
          let name = e.slotName ?? "default"
          // if (e.slotName) {
          let r = ctx[method](e, undefined, isCustom)
          if (!childObj[name]) childObj[name] = []
          childObj[name].push(e)
          res.push(r)
        })
        Object.keys(childObj).forEach((k) => {
          let arr = childObj[k]
          if (arr.length) {
            let val = childObj[k].map((e) =>
              ctx[method](e, undefined, isCustom)
            )
            childObj[k] = () => <Fragment>{val}</Fragment> //{getChildObj(childObj[k])}
          }
        })
        return hasSlot ? childObj : res
        // return [res, childObj]
      }
      let child = flatConf.childNode?.length
        ? getChild(flatConf.childNode, "getComs", isCustom, flatConf.varys)
        : flatConf.innerText ?? flatConf.contentText
      if (isCustom && flatConf.template?.length) {
        child = flatConf.template?.length
          ? getChild(flatConf.template, "getRowItem", isCustom, flatConf.varys)
          : flatConf.innerText ?? flatConf.contentText

        //|| ctx.getRow(flatConf.template)
      }

      // if (flatConf.comName.includes('ollapse')) {
      //   // let a = <div >test11111</div>, b = <div >tes2222</div>
      //   // child = { body: () => <Fragment >{a, b}</Fragment > }
      // }
      //child = (typeof child === 'Object') ? ({ ...child }) : (child)
      //?change
      if (bindProp === null) renderCom = <com {...flatConf}>{child}</com>
      else if (!Array.isArray(bindProp)) {
        renderCom = (
          <com {...flatConf} v-model={ctx.form[flatConf["v_model"]]}>
            {child}
          </com>
        )
      } else {
        try {
          if (bindProp.length === 1)
            renderCom = (
              <com {...flatConf} v-model={ctx.form[flatConf["v_model"][0]]}>
                {child}
              </com>
            )
          if (bindProp.length === 2)
            renderCom = (
              <com
                {...flatConf}
                v-model={
                  ctx.form[flatConf["v_model"][0]][flatConf["v_model"][1]]
                }
              >
                {child}
              </com>
            )
          if (bindProp.length === 3)
            renderCom = (
              <com
                {...flatConf}
                v-model={
                  ctx.form[flatConf["v_model"][0]][flatConf["v_model"][1]][
                    flatConf["v_model"][2]
                  ]
                }
              >
                {child}
              </com>
            )
          if (bindProp.length === 4)
            renderCom = (
              <com
                {...flatConf}
                v-model={
                  ctx.form[flatConf["v_model"][0]][flatConf["v_model"][1]][
                    flatConf["v_model"][2]
                  ][flatConf["v_model"][3]]
                }
              >
                {child}
              </com>
            )
          if (bindProp.length === 5)
            renderCom = (
              <com
                {...flatConf}
                v-model={
                  ctx.form[flatConf["v_model"][0]][flatConf["v_model"][1]][
                    flatConf["v_model"][2]
                  ][flatConf["v_model"][3]][flatConf["v_model"][4]]
                }
              >
                {child}
              </com>
            )
        } catch (error) {
          debugger
        }
      }

      if (flatConf["v_html"]) {
        renderCom = (
          <com {...flatConf} v-html={flatConf["v_html"]}>
            {child}
          </com>
        )
      }

      let extendProp = {}
      let flgDom = (e) => {
        return e?.attributes?.eventObj?.value
      }

      if (ctx.dragEvent?.length) {
        extendProp = {
          onMouseover: (e) => {
            let item = getTargetDom(e.target, flgDom)

            ctx.currentCom = item
            e.stopPropagation()
          },
          onMouseleave: (e) => {
            ctx.currentCom = null
            let item = getTargetDom(e.target, flgDom)
            e.stopPropagation()
          },
          eventObj: conf.selfIndex ?? null,
          class: "isComContainer"
        }
      }
      if (ctx.clickEvent) {
        extendProp = {
          ...extendProp,
          eventObj: flatConf.selfIndex ?? null,
          onClick: (e) => {
            let dom = getTargetDom(e.target, flgDom)

            ctx.$emit(ctx.clickEvent, flatConf, dom)
            e.stopPropagation()
          },
          style: "height:fit-content",
          class: "isComContainer"
        }
      }
      if (conf.formItemProps?.prop || conf.formItemProps?.label) {
        let formItemCom
        let reqclass =
          conf.formItemProps?.isRequired || conf.formItemProps?.required
            ? "is-required"
            : ""
        //class={conf.formItemProps?.isRequired ? "is-required" : ''}
        formItemCom = (
          <ElFormItem {...ctx.getFlatJson(conf.formItemProps)} class={reqclass}>
            {renderCom}
          </ElFormItem>
        )
        if (!extendProp.class) return formItemCom
        return <div {...extendProp}>{formItemCom}</div>
      } else {
        if (!extendProp.class) return renderCom
        return <div {...extendProp}>{renderCom}</div>
      }
    },
    handleVueOrder(conf: any) {
      let ctx = this
      let orderList = ["v_if", "v_show", "v_for"]
      let res = deepClone(conf)
      if ("_" + "v_for" in conf) {
        //暂不处理v_if等指令 可能用到v_for变量
        orderList = ["v_for"]
      }
      orderList.forEach((order) => {
        if ("_" + order in conf) {
          let val =
            ctx.getValInParent(res["_" + order], res?.varys) ??
            ctx.form[res["_" + order]] ??
            undefined
          res[order] = val
          delete res["_" + order]
        }
      }) //change

      if (
        res["v_for"] !== undefined &&
        Array.isArray(res["v_for"]) &&
        res["v_for"].length
      ) {
        let list = res["v_for"][0]
        if (typeof list === "string")
          list = ctx.getValInParent(list, res?.varys) ?? []
        let item = res["v_for"][1] ?? "item"
        let index = res["v_for"][2] ?? "i"
        if (Array.isArray(list)) {
          res = list.map((e, i) => {
            let newConf = deepClone(res) // JSON.parse(JSON.stringify(conf))
            if (!newConf["varys"]) newConf["varys"] = {}
            newConf["varys"][item] = e
            newConf["varys"][index] = i

            orderList = ["v_if", "v_show"]
            //处理v_if等指令
            orderList.forEach((order) => {
              if ("_" + order in newConf) {
                let val =
                  ctx.getValInParent(newConf["_" + order], newConf?.varys) ??
                  ctx.form[newConf["_" + order]] ??
                  undefined
                newConf[order] = val
                delete newConf["_" + order]
              }
            })
            if ("v_if" in newConf) {
              if (!newConf["v_if"] && ctx.useIf !== false) return null
            }
            if ("v_show" in newConf && !newConf["v_show"]) {
              newConf["style"] = newConf["style"]
                ? (newConf["style"] += " display:none; !important")
                : " display:none; !important"
            }
            delete newConf["v_for"]
            return newConf
          })
          return res
        } else if (typeof list === "object" && list !== null) {
          let newRes = []
          Object.keys(list).forEach((k) => {
            let newConf = deepClone(res) // JSON.parse(JSON.stringify(conf))
            if (!newConf["varys"]) newConf["varys"] = {}
            newConf["varys"][item] = list[k]
            newConf["varys"][index] = k
            delete newConf["v_for"]
            newRes.push(newConf)
          })
          return newRes
        }
      }
      if ("v_if" in res) {
        if (!res["v_if"] && ctx.useIf !== false) return null
      }
      if ("v_show" in res && !res["v_show"]) {
        res["style"] = res["style"]
          ? (res["style"] += " display:none; !important")
          : " display:none; !important"
      }
      return res
    }
  },
  watch: {},
  render(ctx) {
    ctx.formProp_conf = markRaw({})
    // ctx.form = new Proxy({}, {
    //   get: (target, prop, c) => {
    //     return ctx.formConf?.props?.model?.[prop];
    //   },
    //   set: (target, prop, value) => {
    //     try {
    //       ctx.formConf?.props?.model[prop] = value;
    //       return true;
    //     } catch (error) {
    //       console.log(error);
    //       return false;
    //     }
    //   },
    // });
    // ctx.form = ctx.formConf?.props?.model ?? {};
    //ctx.form = markRaw(ctx.formConf?.props?.model ?? {});
    if (!ctx.formConf || (!ctx.visible && ctx.visible !== undefined))
      return <div></div>
    // if (ctx.slotName) {
    //   return (<div>{ctx.getRow(ctx.formConf.template)}</div>)
    //   return {
    //     [ctx.slotName]: () => <div>{ctx.getRow(ctx.formConf.template)}</div>
    //   }
    // }
    this.form = this.formConf?.props?.model
    ctx.$nextTick(() => {
      ctx.updateRule()
    })
    if (ctx.dragEvent?.length) {
      return (
        <ElForm
          v-draggable
          {...ctx.getFlatJson(ctx.formConf)}
          model={ctx.form}
          ref={ctx.formName}
          validate-on-rule-change
        >
          {ctx.getRow(ctx.formConf.template)}
        </ElForm>
      )
    }
    return (
      <ElForm
        v-draggable
        {...ctx.getFlatJson(ctx.formConf)}
        rules={ctx.rules}
        model={ctx.form}
        ref={ctx.formName}
      >
        {ctx.getRow(ctx.formConf.template)}
      </ElForm>
    )
  },
  mounted() {
    let ctx = this
    if (!ctx.formConf) return
    ctx.formConf.formRef = () => ctx.$refs[ctx.formName]
    // ctx.form = new Proxy(
    //   {},
    //   {
    //     get: () => ctx.formConf?.props?.model,
    //     set: (a, b, c) => {
    //       ctx.formConf.props.model[b] = c;
    //       return true;
    //     },
    //   }
    // );
    ctx.updateRule(true, "immediate")
  },
  directives: {
    draggable: {
      mounted: function (el, binding, vnode) {
        let ctx = binding.instance
        el.style.cursor = "grab"
        const parent = el
        //parent.style['overflow-y']
        const getUnitDom = (e, loop = 0) => {
          return ctx.currentCom
        }
        const getRowByDom = (dom) => {
          let flg = (e) => {
            if (!e?.className) return false
            // return e?.attributes?.selfIndex?.value?.includes("row_")
            return e?.className?.includes("el-row")
          }
          let rowDom = getTargetDom(dom, flg)
          return rowDom
        }

        el.onmousedown = (e) => {
          if (!ctx.dragEvent?.length) return
          el.style.cursor = "grabbing"
          let el1 = getUnitDom(e.target)
          if (!el1) return
          let unDragItem = ctx.unDragList.find((e) => {
            if (
              el1.attributes.eventobj.value.split("_")[0].toLowerCase() ===
              e.toLowerCase()
            ) {
              return true
            }
          })
          if (unDragItem) return
          ctx.$emit(ctx.dragEvent[0])
          ctx.isMoving = true
          el1.className += " isMoving"
          let { clientX: ox, clientY: oy } = e
          // let beforeIndex = el1?.attributes?.listIndex?.value;
          // if (!beforeIndex) return;
          let curDom = null
          let curRow = null
          let oIndex = el1.style.zIndex
          el1.style.zIndex = "99"
          el1.style.pointerEvents = "none"
          el1.style.opacity = 0.75
          document.onmousemove = function (e) {
            let { clientX: tx, clientY: ty } = e
            el1.style.transform =
              "translate(" + (tx - ox) + "px," + (ty - oy) + "px)"
            // ctx.$nextTick(() => {
            let { x: cx, y: cy } = el1.getBoundingClientRect()
            curDom = document.elementFromPoint(cx, cy)
            if (curRow?.className) {
              curRow.className = curRow.className.replaceAll("isHover", "")
              curRow = null
            }
            curRow = getRowByDom(curDom)
            if (curRow) {
              if (!curRow.className) curRow.className = ""
              curRow.className += " isHover"
            }
            // })
          }
          document.onmouseup = function (e) {
            el1.style.zIndex = oIndex
            let { x: cx, y: cy } = el1.getBoundingClientRect()

            el1.style.transform = "unset"
            el1.style.opacity = "unset"
            el.style.cursor = "grab"
            el1.style.pointerEvents = ""

            document.onmouseup = document.onmousemove = null
            ctx.isMoving = false
            el1.className = el1.className.replaceAll("isMoving", "")
            // setTimeout(function () {
            let index = el1?.attributes?.eventObj?.value
            if (!index) return
            if (!curDom) return
            curDom = document.elementFromPoint(cx, cy)

            if (curRow?.className) {
              curRow.className = curRow.className.replaceAll("isHover", "")
            }
            curRow = null
            ctx.$emit(ctx.dragEvent[1], index, curDom, true, [cx, cy])
            // index = index.split('_')[0]
            // }, 100);
          }
        }
      },
      unmounted(el, binding, vnode) {
        el.onmousedown = null
      }
    }
  }
})
